package com.yueyang.sojourn.server.service.sojourn.sequence;

import com.yueyang.sojourn.server.model.po.SojournSequence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * @author Andy.yang
 * @version v1
 * @summary
 * @Copyright (c) 2019, YueYang Group All Rights Reserved.
 * @since 2020/3/20
 */
@Service
public class SojournSequenceService {
    private static HashMap<String, SojournSequence> sequenceMap = new HashMap<>();

    @Resource
    SojournSequenceMapper sojournSequenceMapper;

    @Transactional
    public Long nextValue(String appName,String sequenceName){
        String key = appName + "-" + sequenceName;
        SojournSequence sequ = sequenceMap.get(key);
        if(sequ == null){
            sequ = sojournSequenceMapper.findBy(appName,sequenceName);
            if(sequ == null){
                throw new RuntimeException("序列[" + key + "]不存在");
            }
            sequenceMap.put(key,sequ);
            sequ.setStartValue(sequ.getNextValue());
        }

        return nextValue(sequ);
    }


    /**
     * 获取下一个
     * @param sequ
     * @return
     */
    @Transactional
    Long nextValue(SojournSequence sequ){
        Long nextValue = 0L;
        // 如果已经增长到了临界值，悲观锁更新临界值，重新计算nextValue
        if ((sequ.getNextValue() - sequ.getStartValue()) % sequ.getStep() == 0) {
            updateValuePlus(sequ);
        }

        nextValue = sequ.getNextValue();
        sequ.setNextValue(nextValue + 1);
        return nextValue;
    }

    @Transactional
    void updateValuePlus(SojournSequence sequ){
        SojournSequence sojournSequence = sojournSequenceMapper.findById(sequ.getId());
        sequ.setStartValue(sojournSequence.getNextValue());
        int udateRs = sojournSequenceMapper.updateValue(sequ.getId(),sojournSequence.getVersion());
        if(udateRs < 1){
            throw new RuntimeException("序列[" + sequ.getAppName() + "-" + sequ.getSequenceName() + "]更新失败");
        }
        sequ.setVersion(sojournSequence.getVersion());
        sequ.setNextValue(sojournSequence.getNextValue() + sojournSequence.getStep());
    }
}
